---
title: BarCodeScanner
description: A library that allows scanning a variety of supported barcodes. It is available both as a standalone library and as an extension for Expo Camera.
sourceCodeUrl: 'https://github.com/expo/expo/tree/main/packages/expo-barcode-scanner'
packageName: 'expo-barcode-scanner'
iconUrl: '/static/images/packages/expo-barcode-scanner.png'
platforms: ['android*', 'ios*']
---

import APISection from '~/components/plugins/APISection';
import { APIInstallSection } from '~/components/plugins/InstallSection';
import { AndroidPermissions, IOSPermissions } from '~/components/plugins/permissions';
import {
  ConfigReactNative,
  ConfigPluginExample,
  ConfigPluginProperties,
} from '~/ui/components/ConfigSection';
import { YesIcon, NoIcon } from '~/ui/components/DocIcons';
import { SnackInline } from '~/ui/components/Snippet';
import { PlatformTags } from '~/ui/components/Tag';

> **warning** **Deprecated:** This library will no longer be available from SDK 51. We recommend using [`expo-camera`](camera) which has barcode scanning built-in instead.

`expo-barcode-scanner` provides a React component that renders a viewfinder for the device's camera (either front or back) and will scan bar codes that show up in the frame.

#### Limitations

> **info** Only one active `BarCodeScanner` preview is currently supported.

When using navigation, the best practice is to unmount any previously rendered `BarCodeScanner` component so the following screens can use their own `BarCodeScanner` without any issue.

#### Known issues&ensp;<PlatformTags platforms={['android', 'ios']} />

The `BarCodeScanner` component has difficulty scanning barcodes with black backgrounds. This is a limitation due to the underlying ZXing library. It is also an issue discussed on a [Stack Overflow thread](https://stackoverflow.com/questions/41518373/zxing-library-not-scanning-qr-code-black-background-and-white-codenegative-scan). To work around this, your app should allow users to capture the barcode image and then invert the colors of the image before passing it to the `BarCodeScanner`.

## Installation

<APIInstallSection />

## Configuration in app.json/app.config.js

You can configure `expo-barcode-scanner` using its built-in [config plugin](/config-plugins/introduction/) if you use config plugins in your project ([EAS Build](/build/introduction) or `npx expo run:[android|ios]`). The plugin allows you to configure various properties that cannot be set at runtime and require building a new app binary to take effect.

<ConfigPluginExample>

```json app.json
{
  "expo": {
    "plugins": [
      [
        "expo-barcode-scanner",
        {
          "cameraPermission": "Allow $(PRODUCT_NAME) to access camera."
        }
      ]
    ]
  }
}
```

</ConfigPluginExample>

<ConfigPluginProperties
  properties={[
    {
      name: 'cameraPermission',
      platform: 'ios',
      description:
        'A string to set the [`NSCameraUsageDescription`](#permission-nscamerausagedescription) permission message.',
      default: '"Allow $(PRODUCT_NAME) to access your camera"',
    },
    {
      name: 'microphonePermission',
      platform: 'ios',
      description:
        'A string to set the [`NSMicrophoneUsageDescription`](#permission-nsmicrophoneusagedescription) permission message.',
      default: '"Allow $(PRODUCT_NAME) to access your microphone"',
    },
  ]}
/>

<ConfigReactNative>

Learn how to configure the native projects in the [installation instructions in the `expo-barcode-scanner` repository](https://github.com/expo/expo/tree/main/packages/expo-barcode-scanner#installation-in-bare-react-native-projects).

</ConfigReactNative>

## Supported formats

| Bar code format | Android     | iOS           |
| --------------- | ----------- | ------------- |
| aztec           | <YesIcon /> | <YesIcon />   |
| codabar         | <YesIcon /> | <YesIcon />   |
| code39          | <YesIcon /> | <YesIcon />\* |
| code93          | <YesIcon /> | <YesIcon />   |
| code128         | <YesIcon /> | <YesIcon />   |
| code39mod43     | <NoIcon />  | <YesIcon />   |
| datamatrix      | <YesIcon /> | <YesIcon />   |
| ean13           | <YesIcon /> | <YesIcon />   |
| ean8            | <YesIcon /> | <YesIcon />   |
| interleaved2of5 | use `itf14` | <YesIcon />   |
| itf14           | <YesIcon /> | <YesIcon />\* |
| maxicode        | <YesIcon /> | <NoIcon />    |
| pdf417          | <YesIcon /> | <YesIcon />\* |
| rss14           | <YesIcon /> | <NoIcon />    |
| rssexpanded     | <YesIcon /> | <NoIcon />    |
| upc_a           | <YesIcon /> | <NoIcon />    |
| upc_e           | <YesIcon /> | <YesIcon />   |
| upc_ean         | <YesIcon /> | <NoIcon />    |
| qr              | <YesIcon /> | <YesIcon />   |

#### Additional notes

1. When an `ITF-14` barcode is recognized, it's type can sometimes be set to `interleaved2of5`.
2. Scanning for either `PDF417` and/or `Code39` formats can result in a noticeable increase in battery consumption on iOS. It is recommended to provide only the bar code formats you expect to scan to the `barCodeTypes` prop.

## Usage

You must request permission to access the user's camera before attempting to get it. To do this, you will want to use the [Permissions](/guides/permissions) API. You can see this in practice in the following example.

<SnackInline label="Basic BarCodeScanner usage" dependencies={['expo-barcode-scanner']}>

```jsx
import React, { useState, useEffect } from 'react';
import { Text, View, StyleSheet, Button } from 'react-native';
import { BarCodeScanner } from 'expo-barcode-scanner';

export default function App() {
  const [hasPermission, setHasPermission] = useState(null);
  const [scanned, setScanned] = useState(false);

  useEffect(() => {
    const getBarCodeScannerPermissions = async () => {
      const { status } = await BarCodeScanner.requestPermissionsAsync();
      setHasPermission(status === 'granted');
    };

    getBarCodeScannerPermissions();
  }, []);

  const handleBarCodeScanned = ({ type, data }) => {
    setScanned(true);
    alert(`Bar code with type ${type} and data ${data} has been scanned!`);
  };

  if (hasPermission === null) {
    return <Text>Requesting for camera permission</Text>;
  }
  if (hasPermission === false) {
    return <Text>No access to camera</Text>;
  }

  return (
    <View style={styles.container}>
      <BarCodeScanner
        onBarCodeScanned={scanned ? undefined : handleBarCodeScanned}
        style={StyleSheet.absoluteFillObject}
      />
      {scanned && <Button title={'Tap to Scan Again'} onPress={() => setScanned(false)} />}
    </View>
  );
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    flexDirection: 'column',
    justifyContent: 'center',
  },
});
```

</SnackInline>

## API

```js
import { BarCodeScanner } from 'expo-barcode-scanner';
```

<APISection packageName="expo-barcode-scanner" apiName="BarCodeScanner" />

## Permissions

### Android

The following permissions are added automatically through this library's `AndroidManifest.xml`:

<AndroidPermissions permissions={['CAMERA']} />

### iOS

The following usage description keys are used by this library:

<IOSPermissions permissions={['NSCameraUsageDescription', 'NSMicrophoneUsageDescription']} />
